package com.wangzhixuan.commons.ueditor;

import com.wangzhixuan.commons.Constant;
import com.wangzhixuan.commons.shiro.ShiroUser;
import com.wangzhixuan.commons.ueditor.define.ActionMap;
import com.wangzhixuan.commons.ueditor.define.AppInfo;
import com.wangzhixuan.commons.ueditor.define.BaseState;
import com.wangzhixuan.commons.ueditor.define.State;
import com.wangzhixuan.commons.ueditor.hunter.ImageHunter;
import com.wangzhixuan.commons.ueditor.manager.IUeditorFileManager;
import com.wangzhixuan.commons.ueditor.upload.Uploader;
import com.wangzhixuan.commons.utils.JsonUtils;
import com.wangzhixuan.service.ISysFileService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

@Component
public class UeditorService {
    @Autowired
    private UeditorManager ueditorManager;
    @Autowired
    private ISysFileService sysFileService;

    public String exec(HttpServletRequest request, String domain, ShiroUser shiroUser) {
        String callbackName = request.getParameter("callback");
        if (callbackName != null) {
            if (!validCallbackName(callbackName)) {
                return new BaseState(false, AppInfo.ILLEGAL).toJSONString();
            }
            return callbackName + "(" + invoke(request, domain, shiroUser) + ");";
        } else {
            return invoke(request, domain, shiroUser);
        }
    }

    private String invoke(HttpServletRequest request, String domain, ShiroUser shiroUser) {
        String actionType = request.getParameter("action");
        String rootPath = Constant.UPLOAD_PATH;
        String defaultPrefix = domain + Constant.VISIT_PATH;
        if (actionType == null || !ActionMap.mapping.containsKey(actionType)) {
            return new BaseState(false, AppInfo.INVALID_ACTION).toJSONString();
        }
        if (ueditorManager == null || !ueditorManager.valid()) {
            return new BaseState(false, AppInfo.CONFIG_ERROR).toJSONString();
        }

        IUeditorFileManager fileManager = ueditorManager.getFileManager();

        State state = null;
        int actionCode = ActionMap.getType(actionType);
        ActionConfig conf = null;

        switch (actionCode) {

            case ActionMap.CONFIG:
                UeditorConfig allConfig = ueditorManager.getConfig();
                String imageUrlPrefix = allConfig.getImageUrlPrefix();
                String scrawlUrlPrefix = allConfig.getScrawlUrlPrefix();
                String snapscreenUrlPrefix = allConfig.getSnapscreenUrlPrefix();
                String catcherUrlPrefix = allConfig.getCatcherUrlPrefix();
                String videoUrlPrefix = allConfig.getVideoUrlPrefix();
                String fileUrlPrefix = allConfig.getFileUrlPrefix();
                String imageManagerUrlPrefix = allConfig.getImageManagerUrlPrefix();
                String fileManagerUrlPrefix = allConfig.getFileManagerUrlPrefix();

                if (StringUtils.isBlank(imageUrlPrefix)) {
                    allConfig.setImageUrlPrefix(defaultPrefix);
                }
                if (StringUtils.isBlank(scrawlUrlPrefix)) {
                    allConfig.setScrawlUrlPrefix(defaultPrefix);
                }
                if (StringUtils.isBlank(snapscreenUrlPrefix)) {
                    allConfig.setSnapscreenUrlPrefix(defaultPrefix);
                }
                if (StringUtils.isBlank(catcherUrlPrefix)) {
                    allConfig.setCatcherUrlPrefix(defaultPrefix);
                }
                if (StringUtils.isBlank(videoUrlPrefix)) {
                    allConfig.setVideoUrlPrefix(defaultPrefix);
                }
                if (StringUtils.isBlank(fileUrlPrefix)) {
                    allConfig.setFileUrlPrefix(defaultPrefix);
                }
                if (StringUtils.isBlank(imageManagerUrlPrefix)) {
                    allConfig.setImageManagerUrlPrefix(defaultPrefix);
                }
                if (StringUtils.isBlank(fileManagerUrlPrefix)) {
                    allConfig.setFileManagerUrlPrefix(defaultPrefix);
                }
                return JsonUtils.toJson(allConfig);

            case ActionMap.UPLOAD_IMAGE:
            case ActionMap.UPLOAD_SCRAWL:
            case ActionMap.UPLOAD_VIDEO:
            case ActionMap.UPLOAD_FILE:
                conf = ueditorManager.getConfig(actionCode, rootPath);
                state = new Uploader(request, conf).doExec(fileManager);
                if (state != null && state.isSuccess()) {
                    Map<String, Object> infoMap = state.toJSONObject();
                    String suffix = String.valueOf(infoMap.get("type"));
                    suffix = StringUtils.isBlank(suffix) ? suffix : suffix.substring(1);
                    String url = String.valueOf(infoMap.get("url"));
                    String realPath = rootPath + url;
                    String visitUrl = defaultPrefix + url;
                    sysFileService.saveFile(String.valueOf(infoMap.get("original")), suffix, Long.valueOf(String.valueOf(infoMap.get("size"))), realPath, visitUrl, "ueditor上传文件");
                }
                break;

            case ActionMap.CATCH_IMAGE:
                conf = ueditorManager.getConfig(actionCode, rootPath);
                String[] list = request.getParameterValues(conf.getFieldName());
                state = new ImageHunter(fileManager, conf).capture(list);
                break;

            case ActionMap.LIST_IMAGE:
            case ActionMap.LIST_FILE:
                conf = ueditorManager.getConfig(actionCode, rootPath);
                int start = getStartIndex(request);
                state = fileManager.list(conf, start);
                break;

        }
        return state.toJSONString();
    }

    public int getStartIndex(HttpServletRequest request) {
        String start = request.getParameter("start");
        try {
            return Integer.parseInt(start);
        } catch (Exception e) {
            return 0;
        }
    }

    /**
     * callback参数验证
     *
     * @param name 参数名
     * @return boolean 是否校验通过
     */
    public boolean validCallbackName(String name) {
        return name.matches("^[a-zA-Z_]+[\\w0-9_]*$");
    }
}
